package pl.alef.web.inter;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;

import pl.alef.mindplay.dao.UserAgentDAO;
import pl.alef.mindplay.dao.VisitDAO;
import pl.alef.mindplay.model.RemoteAddress;
import pl.alef.mindplay.model.UserAgent;
import pl.alef.mindplay.model.Visit;
import pl.alef.mindplay.model.Visitor;
import pl.alef.mindplay.services.VisitService;
import pl.alef.mindplay.services.impl.RemoteAddressHelper;
import pl.alef.utils.http.HttpHeaders;

public class A1 implements HandlerInterceptor  {

	public static final String COOKIE_NAME = "vqacy";
	public static final String SESSION_VISIT_ATTR = "visit";
	
	final static Logger logger = LoggerFactory.getLogger(A1.class);
	
	@Autowired
	protected VisitService visitService;
	
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		
		HttpSession session = request.getSession(true);
		
		Visit visit = (Visit) session.getAttribute(SESSION_VISIT_ATTR);
		final Date now = Calendar.getInstance().getTime();
		
		if(visit == null) {
			visit = new Visit();
			visit.setDateStart(now);		
			
			String userAgentName = request.getHeader(HttpHeaders.USER_AGENT);
			logger.debug("user-agent-header = {}", userAgentName);
			visit.setUserAgent(visitService.getUserAgentByName(userAgentName));
			
			final String refererName = request.getHeader(HttpHeaders.REFERER);
			logger.debug("referer-header = {}", refererName);
			visit.setReferer(visitService.getRefererByName(refererName));
			
			Map<String, String> addresses = RemoteAddressHelper.getAddresses(request);
			
			logger.info("addrs = {}", addresses);
			
			Map<String, RemoteAddress> map = new HashMap<String, RemoteAddress>(addresses.size()*2+1);
			for (Map.Entry<String,String> entry : addresses.entrySet()) {
				RemoteAddress address = new RemoteAddress();
				address.setAddr(entry.getValue());
				address.setType(entry.getKey());
				address.setVisit(visit);
				map.put(entry.getKey(), address);
			}
			
			visit.setAddresses(map);
			
			Long idVisitor = getLongFromCookie(request, COOKIE_NAME);
			
			Visitor visitor = new Visitor();
			visit.setVisitor(visitor);
			visitor.setId(idVisitor);
			
			visit.setCnt(1);
			
		} else {
			visit.setDateEnd(now);
			visit.setCnt(visit.getCnt()+1);
		}
		
		try {
			visitService.save(visit);
		} catch(Exception e) {
			logger.error("Failed to save visit : {}", visit);
			logger.error("Exception :", e);
		}
		
		session.setAttribute(SESSION_VISIT_ATTR, visit);
		return true;
	}

	private Long getLongFromCookie(HttpServletRequest request, String cookieName) {
		Cookie cookie = WebUtils.getCookie(request, COOKIE_NAME);		
		if(cookie != null) {
			try {
				return Long.valueOf(cookie.getValue());
			} catch (NumberFormatException e) {
				logger.info("Invalid value in cookie[{}] = {}", COOKIE_NAME, cookie.getValue());
			}
		}
		return null;
	}

	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		logger.debug("> postHandle");
		if(request.getSession(false) != null) {
			Visit visit = (Visit) request.getSession(false).getAttribute(SESSION_VISIT_ATTR);
			addCookie(response, COOKIE_NAME ,visit.getVisitor().getId());
		}

	}

	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	}
	
	void addCookie(HttpServletResponse response, String cookieName, Long value) {
		logger.debug("Store value = {} in cookie : '{}'", value, cookieName);
		Cookie cookie = new Cookie(COOKIE_NAME, value.toString());
		int expiry = 365 * 24 * 3600;
		cookie.setMaxAge(expiry);
		response.addCookie(cookie);				
	}
	
	
	

}
